use std::collections::HashMap;
use chrono::{Duration, prelude};
use reqwest::header::USER_AGENT;
use serde::{Deserialize, Serialize};
use crate::client::login::{Cookie, Form, LoginProgress};
use reqwest::{header, Response};
use serde::de::DeserializeOwned;
use urlencoding::encode;
use crate::Client;
use crate::client::const_variable::{CSRF_TOKEN, PHPSESSID, YB_USER_AGENT};
use crate::module::daily_form::DailyForm;
use crate::module::identity::UserIdentity;
use crate::module::process_detail::ProcessDetail;
use crate::module::task::TaskForm;
use crate::module::task_detail::TaskDetail;
use crate::module::uncompleted_task::UncompletedTask;


/// 易班服务器返回值
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct YBResponse<T> where T: Serialize {
    pub code: i64,
    pub msg: String,
    pub data: T,
}


impl Client {
    pub async fn base_get<T: Serialize + ?Sized>(&self, url: &str, query: &T) -> anyhow::Result<Response> {
        let client = reqwest::Client::new();
        Ok(client.get(url)
            .query(query)
            .header(header::ORIGIN, "https://c.uyiban.com")
            .header(header::COOKIE, self.cookie.to_form_string(
                &[CSRF_TOKEN, PHPSESSID], "=", ";", "",
            ))
            .header(USER_AGENT, YB_USER_AGENT)
            .send().await?)
    }
    pub async fn base_post<T: Serialize + ?Sized, S: Serialize + ?Sized>(&self, url: &str, query: &S, form: &T) -> anyhow::Result<Response> {
        let client = reqwest::Client::new();
        Ok(client.post(url)
            .query(query)
            .header(header::ORIGIN, "https://c.uyiban.com")
            .header(header::COOKIE, self.cookie.to_form_string(
                &[CSRF_TOKEN, PHPSESSID], "=", ";", "",
            ))
            .header(header::USER_AGENT, YB_USER_AGENT)
            .form(form)
            .send().await?)
    }

    pub async fn get_userinfo(&self) -> anyhow::Result<YBResponse<UserIdentity>> {
        Ok(self.base_get("https://api.uyiban.com/base/c/auth/yiban",
                         &[("CSRF", self.cookie.get(CSRF_TOKEN).unwrap())])
            .await?.
            json::<YBResponse<UserIdentity>>()
            .await?)
    }
    /// 获取未完成的任务
    pub async fn query_uncompleted_tasks(&self) -> anyhow::Result<YBResponse<Vec<UncompletedTask>>> {
        let now = prelude::Local::now();
        let fmt = "%Y-%m-%d 23:59";
        let end_time = now.format(fmt).to_string();
        let start_time = now.checked_sub_signed(Duration::days(15)).unwrap()
            .format("%Y-%m-%d 00:00").to_string();
        Ok(self.base_get("https://api.uyiban.com/officeTask/client/index/uncompletedList"
                         , &[("CSRF", &self.cookie.get(CSRF_TOKEN).unwrap())
                , ("StartTime", &&encode(&start_time).to_string()),
                ("EndTime", &&encode(&end_time).to_string())])
            .await?
            .json::<YBResponse<Vec<UncompletedTask>>>()
            .await?)
    }
    /// 根据任务ID获取详细信息，提交表单需要工作流ID
    pub async fn get_task_detail(&self, task_id: &str) -> anyhow::Result<YBResponse<TaskDetail>> {
        Ok(self.base_get("https://api.uyiban.com/officeTask/client/index/detail"
                         , &[("CSRF", self.cookie.get(CSRF_TOKEN).unwrap().as_str()),
                ("TaskId", task_id)])
            .await?
            .json::<YBResponse<TaskDetail>>()
            .await?)
    }
    pub async fn get_process_detail(&self, workflow_id: &str) -> anyhow::Result<YBResponse<ProcessDetail>> {
        Ok(self.base_get("https://api.uyiban.com/workFlow/c/my/getProcessDetail"
                         , &[("CSRF", self.cookie.get(CSRF_TOKEN).unwrap().as_str()),
                ("WFId", workflow_id)])
            .await?
            .json::<YBResponse<ProcessDetail>>()
            .await?)
    }

    /// 获取日报的信息，此接口目前有错误
    ///
    pub async fn get_daily_form(&self, task_id: &str) -> anyhow::Result<YBResponse<DailyForm>> {
        Ok(self.base_get(&format!("https://api.uyiban.com/workFlow/c/my/form/{}", task_id)
                         , &[("CSRF", self.cookie.get(CSRF_TOKEN).unwrap().as_str()), ])
            .await?
            .json::<YBResponse<DailyForm>>()
            .await?)
    }


    /// 提交任务，需要四个信息，任务ID,工作流ID，数据（包含表单信息），扩展信息（任务附带信息，发布人等）
    pub async fn submit_task(&self, task: TaskForm<'_>) -> anyhow::Result<YBResponse<String>> {
        Ok(self.base_post(&format!("https://api.uyiban.com/workFlow/c/my/apply/{}", task.wf_id),
                          &[
                              ("CSRF", self.cookie.get(CSRF_TOKEN).unwrap().as_str())
                          ], &["Str", &task.encrypted().unwrap()])
            .await?
            .json::<YBResponse<String>>()
            .await?)
    }
}
